/*
 * cxxomfort example: plus
 * 
 * This program provides sample usage of the 
 * "transparent functor" feature.
 * 
 * The program will take text as input until an end-of-file indicator is sent.
 * Text willl then be processed in search of vowels. The aggregation of vowels 
 * per line is done via std::accumulate using a re-defined operator% 
 * (itself wrapped via transparent modulus<>).
 * 
 * As an added point, this also tests that 
 * CXXO_FOREACH is working correctly.
 * 
 */

#include <cxxomfort/cxxomfort.hpp>
// functional
#include <functional>
#include <string>
#include <deque>
#include <sstream>
#include <numeric>
#include <map>
#include <cxxomfort/library/foreach.hpp>


struct Foo {
    std::array<unsigned int,5> sarr;
    explicit Foo(std::string const& q)
    : sarr()  {
        using namespace std;
        if (q.length() >0) {
            for (size_t s= 0; s < q.length(); ++s) { 
                if (false) {}
                else if (tolower(q[s] == 'a')) sarr[0]++;
                else if (tolower(q[s] == 'e')) sarr[1]++;
                else if (tolower(q[s] == 'i')) sarr[2]++;
                else if (tolower(q[s] == 'o')) sarr[3]++;
                else if (tolower(q[s] == 'u')) sarr[4]++;
            } // for
        }
    }
    
};

struct FooMap {
    typedef std::map<unsigned int, unsigned int> datatype;
    typedef datatype::const_iterator datatype_iterator;
    datatype map;
};

FooMap operator+ (FooMap const& fm, Foo const& foo);


typedef std::deque<Foo> Container;

int main () {
    using namespace std;
    Container cont;
    string sin;
    while ( getline(cin,sin) ) {
        cont.push_back( Foo(sin) );
    }
    FooMap themap;
    // this is where the magic happens
    themap= accumulate ( begin(cont), end(cont), themap, plus<void>()  );
    
    CXXO_FOREACH( FooMap::datatype::value_type const& k, themap.map) {
        cout<< (char)(k.first)<< " -> "<< k.second<< endl;
    }
}


FooMap operator+ (FooMap const& fm, Foo const& foo) {
    FooMap ret(fm);
    (ret.map)['a']+= foo.sarr[0];
    (ret.map)['e']+= foo.sarr[1];
    (ret.map)['i']+= foo.sarr[2];
    (ret.map)['o']+= foo.sarr[3];
    (ret.map)['u']+= foo.sarr[4];
    return ret;
}


